package com.lumlord.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicLong;

@Component
public class SyncLog {

    public static ApplicationContext staticApplicationContext;
    public static String staticSpringApplicationName;

    private static String staticServerAction;
    private static LoadBalancerClient staticLoadBalancerClient;
    private static RestTemplate staticRestTemplate;
    private static String staticSyncWebSocket;

    public static boolean isSupportClazz(String clazz){
        if(clazz.toLowerCase().indexOf("log")!=-1){
            return false;
        }
        return  true;
    }

    public static void log(Map tags, Map fields,String clazz, boolean isAop) {

        if(!isSupportClazz(clazz)){
            return;
        }

        blockLogThread.submit(() -> {
            String server = getServer();
            if(server==null){
                return;
            }

            HttpHeaders headers = new HttpHeaders();
            //定义请求参数类型，这里用json所以是MediaType.APPLICATION_JSON
            headers.setContentType(MediaType.APPLICATION_JSON);
            //RestTemplate带参传的时候要用HttpEntity<?>对象传递
            // fields.putAll(tags);

            Map httpArgs = new HashMap();
            httpArgs.put("tags", tags);
            httpArgs.put("fields", fields);
            httpArgs.put("serverName", staticSpringApplicationName);
            httpArgs.put("syncWebSocket",staticSyncWebSocket);
            HttpEntity<Map> request = new HttpEntity<>(httpArgs, headers);
            String action;
            if (isAop) {
                action = server+"/log/send/system/aop";
            } else {
                action = server+"/log/send/system/full";
            }
            staticRestTemplate.postForEntity(action, request, Map.class);
        });

    }


    private static String getServer(){
        if(null == staticServerAction || staticServerAction.trim().length()==0){
            return null;
        }else if(staticServerAction.indexOf("http")!=-1){
            return  staticServerAction;
        }else{
            ServiceInstance serviceInstance = staticLoadBalancerClient.choose(staticServerAction);
            if(serviceInstance==null){
                return null;
            }
            return serviceInstance.getUri().toString();
        }
    }

    private static final java.util.concurrent.ExecutorService blockLogThread = Executors.newFixedThreadPool(40, new ThreadFactory() {
        private final AtomicLong threadIndex = new AtomicLong(0);

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r, "Lumlord-log-influx-" + this.threadIndex.incrementAndGet());
            thread.setDaemon(true);
            return thread;
        }
    });


    @PostConstruct
    public void init() {
        staticApplicationContext = applicationContext;
        staticSpringApplicationName = springApplicationName;
        staticServerAction = serverAction;
        staticLoadBalancerClient = loadBalancer;
        staticRestTemplate = restTemplate;
        staticSyncWebSocket = syncWebSocket;
    }


    @Autowired
    private ApplicationContext applicationContext;
    @Value("${spring.application.name}")
    private String springApplicationName;
    @Value("${lumlord.log.serverAction:}")
    private String serverAction;
    @Value("${lumlord.log.syncWebSocket:false}")
    private String syncWebSocket;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private LoadBalancerClient loadBalancer;
}
